package com.zhpan.indicator.drawer;

import com.zhpan.indicator.enums.IndicatorSlideMode;
import com.zhpan.indicator.options.IndicatorOptions;
import com.zhpan.indicator.utils.ArgbEvaluator;
import com.zhpan.indicator.utils.IndicatorUtils;

import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;

/**
 * 圆形
 *
 * @since 2021-04-13
 */
public class CircleDrawer extends BaseDrawer {
    private RectFloat mRectF;

    /**
     * 更具配置创建圆形
     *
     * @param options 配置
     */
    public CircleDrawer(IndicatorOptions options) {
        super(options);
        mPaint.setAntiAlias(true);
        mRectF = new RectFloat();
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mOptions.getPageSize() > 1) {
            drawNormal(canvas);
            drawSlider(canvas);
        }
    }

    private void drawSlider(Canvas canvas) {
        mPaint.setColor(mOptions.getCheckedSliderColor());
        switch (mOptions.getSlideMode()) {
            case IndicatorSlideMode.NORMAL:
            case IndicatorSlideMode.SMOOTH:
                drawCircleSlider(canvas);
                break;
            case IndicatorSlideMode.WORM:
                drawWormSlider(canvas);
                break;
            case IndicatorSlideMode.SCALE:
                drawScaleSlider(canvas);
                break;
            case IndicatorSlideMode.COLOR:
                this.drawColor(canvas);
                break;
            default:
        }
    }

    private void drawScaleSlider(Canvas canvas) {
        int currentPosition = mOptions.getCurrentPosition();
        float slideProgress = mOptions.getSlideProgress();
        float coordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, currentPosition);
        float coordinateY = IndicatorUtils.getCoordinateY(maxWidth);
        if (slideProgress < 1) {
            int evaluate = (int) ArgbEvaluator.evaluate(slideProgress, mOptions.getCheckedSliderColor().getValue(), mOptions.getNormalSliderColor().getValue());
            mPaint.setColor(new Color(evaluate));
            float radius = mOptions.getCheckedSliderWidth() / 2 - (mOptions.getCheckedSliderWidth()
                / 2 - mOptions.getNormalSliderWidth() / 2) * slideProgress;
            drawCircle(canvas, coordinateX, coordinateY, radius);
        }

        if (currentPosition == mOptions.getPageSize() - 1) {
            int evaluate = (int) ArgbEvaluator.evaluate(slideProgress,
                mOptions.getNormalSliderColor().getValue(), mOptions.getCheckedSliderColor().getValue());
            mPaint.setColor(new Color(evaluate));
            float nextCoordinateX = maxWidth / 2;
            float nextRadius = minWidth / 2 + (maxWidth / 2 - minWidth / 2) * slideProgress;
            drawCircle(canvas, nextCoordinateX, coordinateY, nextRadius);
        } else {
            if (slideProgress > 0) {
                int evaluate = (int) ArgbEvaluator.evaluate(slideProgress,
                    mOptions.getNormalSliderColor().getValue(), mOptions.getCheckedSliderColor().getValue());
                mPaint.setColor(new Color(evaluate));
                float nextCoordinateX = coordinateX + mOptions.getSliderGap() + mOptions.getNormalSliderWidth();
                float nextRadius = mOptions.getNormalSliderWidth() / 2
                    + (mOptions.getCheckedSliderWidth() / 2 - mOptions.getNormalSliderWidth() / 2) * slideProgress;
                drawCircle(canvas, nextCoordinateX, coordinateY, nextRadius);
            }
        }
    }

    /**
     * 手指往右滑动， right 应该是当前，left应该越来越小
     *
     * @param canvas
     */
    private void drawWormSlider(Canvas canvas) {
        float sliderH = mOptions.getNormalSliderWidth();
        float slideProgress = mOptions.getSlideProgress();
        int currentPosition = mOptions.getCurrentPosition();
        float distance = mOptions.getSliderGap() + mOptions.getNormalSliderWidth();
        float startCoordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, currentPosition);
        float left = startCoordinateX + coerceAtLeast(distance * (slideProgress - 0.5f) * 2.0f, 0f)
            - mOptions.getNormalSliderWidth() / 2 + INDICATOR_PADDING;
        float right = startCoordinateX + coerceAtMost(distance * slideProgress * 2.0f, distance)
            + mOptions.getNormalSliderWidth() / 2 + INDICATOR_PADDING;
        mRectF.modify(left, INDICATOR_PADDING, right, sliderH + INDICATOR_PADDING);
        canvas.drawRoundRect(mRectF, sliderH, sliderH, mPaint);
    }

    private void drawCircleSlider(Canvas canvas) {
        int currentPosition = mOptions.getCurrentPosition();
        float startCoordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, currentPosition);
        float endCoordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth,
            (currentPosition + 1) % mOptions.getPageSize());
        float coordinateX = startCoordinateX + (endCoordinateX - startCoordinateX) * mOptions.getSlideProgress();
        float coordinateY = IndicatorUtils.getCoordinateY(maxWidth);
        float radius = mOptions.getCheckedSliderWidth() / 2;
        drawCircle(canvas, coordinateX, coordinateY, radius);
    }

    private void drawColor(Canvas canvas) {
        int currentPosition = mOptions.getCurrentPosition();
        float slideProgress = mOptions.getSlideProgress();
        float coordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, currentPosition);
        float coordinateY = IndicatorUtils.getCoordinateY(maxWidth);
        int evaluate = (int) ArgbEvaluator.evaluate(slideProgress,
            mOptions.getCheckedSliderColor().getValue(), mOptions.getNormalSliderColor().getValue());
        mPaint.setColor(new Color(evaluate));
        drawCircle(canvas, coordinateX, coordinateY, mOptions.getNormalSliderWidth() / 2);
        evaluate = (int) ArgbEvaluator.evaluate(1 - slideProgress,
            mOptions.getCheckedSliderColor().getValue(), mOptions.getNormalSliderColor().getValue());
        mPaint.setColor(new Color(evaluate));
        float nextCoordinateX;
        if (currentPosition == mOptions.getPageSize() - 1) {
            nextCoordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, 0);
        } else {
            nextCoordinateX = coordinateX + mOptions.getSliderGap() + mOptions.getNormalSliderWidth();
        }
        drawCircle(canvas, nextCoordinateX, coordinateY, mOptions.getCheckedSliderWidth() / 2);
    }

    private void drawNormal(Canvas canvas) {
        float normalSliderWidth = mOptions.getNormalSliderWidth();
        mPaint.setColor(mOptions.getNormalSliderColor());
        int pageSize = mOptions.getPageSize();
        for (int i = 0; i < pageSize; i++) {
            float coordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, i);
            float coordinateY = IndicatorUtils.getCoordinateY(maxWidth);
            drawCircle(canvas, coordinateX, coordinateY, normalSliderWidth / 2);
        }
    }

    private void drawCircle(Canvas canvas, float coordinateX, float coordinateY, float radius) {
        canvas.drawCircle(coordinateX + INDICATOR_PADDING, coordinateY + INDICATOR_PADDING, radius, mPaint);
    }

    @Override
    protected int measureHeight() {
        return (int) (maxWidth + INDICATOR_PADDING_ADDITION);
    }
}
